#include <GameEngine/Gameplay/Statistics/statistics_manager.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

#ifndef DOXYGEN_IGNORE
#include "statistics_manager.moc"
#endif

//=================================================================================


//! Default constructor
/*!
 *  The initial collection of statistics is set empty
 */
StatisticsManager::StatisticsManager() : QObject() {}

//! Copy constructor
/*!
 @param rhs The statistics manager to copy
 */
StatisticsManager::StatisticsManager(const StatisticsManager& rhs) : stats_(rhs.stats_), QObject() {}

//! Assignment operator
/*!
 @param rhs The statistics manager to copy
 */
StatisticsManager& StatisticsManager::operator=(const StatisticsManager& rhs) {
	if ( &rhs != this ) {
		stats_ = rhs.stats_;
	}
	return *this;
}

//! Destructor
StatisticsManager::~StatisticsManager() {}

//! Check if the statistics manager manages the given statistics
/*!
 @param name The name of the statistics to locate
 @return True if the statistics manager manages the given statistics, false otherwise
 */
bool StatisticsManager::has_stat(const GEString& name) const {
	// Try to locate the statistics
	QMap<GEString,Statistics>::const_iterator it = stats_.find(name);

	// Return result
	return ( it != stats_.end() );
}

//! Add a new statistics to the collection of statistics managed by the statistics manager
/*!
 @param name The name of the statistics to be added
 @param stat The state of the statistics to be added
 @return True if the statistics could be added, false otherwise. A statistics may not be
         added if a statistic with the same name is already managed by the statistics manager
 */
bool StatisticsManager::add_stat(const GEString& name, Statistics& stat) {
	// Check if the statistics already exists
	if ( has_stat(name) ) return false;

	// Add the statistics
	QMap<GEString,Statistics>::iterator it = stats_.insert(name, stat);
	return ( it != stats_.end() );
}

//! Remove a statistics from the collection of statistics managed by the statistics manager
/*!
 @param name The name of the statistics to be removed
 @return True if the statistics could be removed, false otherwise. A statistics may not be
         removed if no statistic with the given name is managed by the statistics manager
 */
bool StatisticsManager::remove_stat(const GEString& name) {
	return ( stats_.remove(name) > 0 );
}

//! Retrieves the given statistics from the statistics manager (read only)
/*!
 @param name The name of the statistics to retrieve
 @param stat Receives the state of the statistics, if managed by the statistics manager
 @return True if the statistics manager manages the given statistics, false otherwise
 @note Any change that affects the variable stat will NOT be reflected to the content
       of the statistics manager. To update the statistics manager, please call the
	   set_stat function
 */
bool StatisticsManager::get_stat(const GEString& name, Statistics& stat) const {
	// Try to locate the statistics
	QMap<GEString,Statistics>::const_iterator it = stats_.find(name);

	// Return result
	if ( it == stats_.end() ) return false;
	stat = *it;
	return true;
}

//! Change the given statistics in the statistics manager
/*!
 @param name The name of the statistics to change
 @param stat The new state of the statistics
 @return True if the statistics could be changed, false otherwise. A change in the statistics
         is impossible if the statistics is not handled by the statistics manager, or if the
		 statistics is currently locked
 */
bool StatisticsManager::set_stat(const GEString& name, const Statistics& stat) {
	// Try to locate the statistics
	QMap<GEString,Statistics>::iterator it = stats_.find(name);
	if ( it == stats_.end() ) return false;

	// Check that the statistics is not locked
	if ( it->locked() ) return false;

	// Change the statistics
	*it = stat;
	emit statistics_changed(name);
	return true;
}

//! Lock the given statistics
/*!
 @return True if the statistics could be locked, false otherwise. A change in the statistics
         is impossible if the statistics is not handled by the statistics manager
 */
bool StatisticsManager::lock_stat(const GEString& name) {
	// Try to locate the statistics
	QMap<GEString,Statistics>::iterator it = stats_.find(name);
	if ( it == stats_.end() ) return false;

	// Change the statistics
	it->locked() = true;
	return true;
}

//! Unlock the given statistics
/*!
 @return True if the statistics could be unlocked, false otherwise. A change in the statistics
         is impossible if the statistics is not handled by the statistics manager
 */
bool StatisticsManager::unlock_stat(const GEString& name) {
	// Try to locate the statistics
	QMap<GEString,Statistics>::iterator it = stats_.find(name);
	if ( it == stats_.end() ) return false;

	// Change the statistics
	it->locked() = false;
	return true;
}

//! Give access to the name of all statistics managed by the statistics manager
/*!
 @return The name of all statistics managed by the statistics manager
 */
QList<GEString> StatisticsManager::stat_names() const {
	return stats_.uniqueKeys();
}


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
